/*
MayPack v0.1
Copyright (c) 2021 Majjcom
licence:	MIT
Date:		2021/12/16
FILE:		packer.cpp
*/
#include <filesystem>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include "include/mayjson/may.h"

std::string changeIntToCharAtTail(int i);

#pragma warning(disable : 4996)
namespace maypack
{
	int packUp(std::vector<std::string> packs, const int count, const char fout[])
	{
		if (std::string(fout).find('/') != std::string::npos || std::string(fout).find('\\') != std::string::npos)
		{
			return 3;
		}
		for (int i = 0; i < count; i++)
		{
			if (packs[i].find('\\') != std::string::npos || packs[i].find('/') != std::string::npos)
			{
				return 1;
			}
			if (!std::experimental::filesystem::exists(std::experimental::filesystem::path(packs[i])))
			{
				return 2;
			}
		}
		FILE* fp_out = fopen("fout_temp", "wb+");
		FILE* fp_out_fin = fopen(fout, "wb");
		mayjson::Json info_main;
		info_main.setUp("{}");
		info_main.setValue("count", count);
		std::vector<char*> charPool;
		for (int i = 0; i < count; i++)
		{
			FILE* fp_in = fopen(packs[i].c_str(), "rb");
			fseek(fp_in, 0, SEEK_END);
			int size = ftell(fp_in);
			int pos = ftell(fp_out);
			fseek(fp_in, 0, SEEK_SET);
			mayjson::Json info_loc;
			info_loc.setUp("{}");
			info_loc.setValue("name", packs[i].c_str());
			info_loc.setValue("pos", pos);
			info_loc.setValue("size", size);
			char buff;
			int rc;
			while (rc = fread(&buff, sizeof(char), 1, fp_in) != 0)
			{
				fwrite(&buff, sizeof(char), 1, fp_out);
			}
			char* index = new char[4];
			charPool.resize(charPool.size() + 1);
			charPool[charPool.size() - 1] = index;
			itoa(i, index, 10);
			info_main.setValue(index, info_loc);
			fclose(fp_in);
		}
		fseek(fp_out, 0, SEEK_SET);
		std::string info_out = info_main.getStr();
		const char* info_out_c = info_out.c_str();
		// Head prase
		std::string head = changeIntToCharAtTail(strlen(info_out_c) * sizeof(char));
		fwrite(head.c_str(), sizeof(char), 16, fp_out_fin);
		fwrite(info_out_c, sizeof(char), strlen(info_out_c), fp_out_fin);
		// Body prase
		{
			char buff;
			int rc;
			while (rc = fread(&buff, sizeof(char), 1, fp_out) != 0)
			{
				fwrite(&buff, sizeof(char), 1, fp_out_fin);
			}
		}
		fclose(fp_out);
		fclose(fp_out_fin);
		info_main.release();
		for (int i = 0; i < int(charPool.size()); i++)
		{
			delete charPool[i];
		}
		std::experimental::filesystem::remove(std::experimental::filesystem::path("fout_temp"));
		return 0;
	}
}

std::string changeIntToCharAtTail(int i)
{
	char length_a[16];
	char length[16];
	int len = 0;
	itoa(i, length_a, 10);
	for (int i = 0; i < 16; i++)
	{
		if (length_a[i] == '\0')
		{
			break;
		}
		len++;
	}
	for (int i = 15; i >= 0; i--)
	{
		if (i > 15 - len)
		{
			length[i] = length_a[i - (16 - len)];
		}
		else
		{
			length[i] = '0';
		}
	}
	return std::string(length);
}

